/**
 * Copyright 2013 wasu.com
 *
 *
 * Create on 2014-7-29 下午11:52:45
 */
package xiaojian.toolkit.netty.handler.codec.http.encode;

import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import xiaojian.toolkit.bean.bytebean.core.BeanFieldCodec;
import xiaojian.toolkit.bean.json.annotation.JSONMessage;
import xiaojian.toolkit.netty.handler.codec.tlv.NettyMixedTcpEncoder;
import xiaojian.toolkit.transport.protocol.xip.XipHeader;
import xiaojian.toolkit.util.MutableIdentifyable;

import com.alibaba.fastjson.JSON;
import com.google.common.primitives.Bytes;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

/**
 * 将json数据的报文，编码为头为xipheader、正文为json的数据流，方便在网络上传输。
 * 
 * @author <a href="mailto:caoxiaojian@wasu.com>xiaojian.cao</a>
 * 
 */
@ChannelHandler.Sharable
public class MixedJsonEncoder extends MessageToByteEncoder<MutableIdentifyable> {

	private static final Logger logger = LoggerFactory
			.getLogger(NettyMixedTcpEncoder.class);

	private BeanFieldCodec xipBeanCodec;

	/**
	 * @see io.netty.handler.codec.MessageToByteEncoder#encode(io.netty.channel.ChannelHandlerContext,
	 *      java.lang.Object, io.netty.buffer.ByteBuf)
	 */
	@Override
	protected void encode(ChannelHandlerContext ctx, MutableIdentifyable msg,
			ByteBuf out) throws Exception {
		JSONMessage jm = msg.getClass().getAnnotation(JSONMessage.class);
		if (jm == null) {
			throw new RuntimeException(
					"invalid json message, missing @JSONMessage.");
		}

		final UUID id = ((MutableIdentifyable) msg).getIdentification();
		if (logger.isDebugEnabled()) {
			logger.debug("encoding JSONObject {} to wrappedBuffer", msg);
		}
		if (null != id) {
			final String jsonString = JSON.toJSONString(msg);
			final byte[] jsonBytes = jsonString.getBytes("UTF-8");
			out.writeBytes(Bytes.concat(this.getHeader((byte) 100, id,
					jm.messageCode(), jsonBytes.length), jsonBytes));
		} else {
			if (logger.isWarnEnabled()) {
				logger.warn("{} is json but missing transactionId", msg);
			}
		}

	}

	private byte[] getHeader(byte basicVer, UUID id, int messageCode,
			int messageLen) {
		final XipHeader header = new XipHeader();
		header.setTransaction(id);
		header.setLength(xipBeanCodec.getStaticByteSize(XipHeader.class)
				+ messageLen);
		header.setMessageLength(messageLen);
		header.setMessageCode(messageCode);
		header.setBasicVer(basicVer);

		return xipBeanCodec.encode(xipBeanCodec.getEncContextFactory()
				.createEncContext(header, XipHeader.class, null));
	}

	public BeanFieldCodec getXipBeanCodec() {
		return xipBeanCodec;
	}

	public void setXipBeanCodec(BeanFieldCodec xipBeanCodec) {
		this.xipBeanCodec = xipBeanCodec;
	}

}
